<?php

declare(strict_types=1);

namespace Plugin\Attractions\Broadcast\Job;

use Common\Common;
use Hyperf\AsyncQueue\Job;
use Hyperf\Coroutine\Coroutine;
use Hyperf\DbConnection\Db;
use Plugin\Attractions\Broadcast\Constant;
use Plugin\Attractions\Broadcast\Repository\Broadcast_devices\BroadcastDevicesRepository;
use Plugin\Attractions\Broadcast\Repository\Broadcast_execution_log\BroadcastExecutionLogRepository;
use Plugin\Attractions\Broadcast\Repository\Broadcast_plans\BroadcastPlansRepository;
use Throwable;

class BroadcastJob extends Job
{
    public $params;

    /**
     * 任务执行失败后的重试次数，即最大执行次数为 $maxAttempts+1 次
     */
    protected int $maxAttempts = 1;

    public function __construct($params)
    {
        $this->params = $params;
    }

    public function handle()
    {
        $params = $this->params;
        $planRepo = Common::container()->get(BroadcastPlansRepository::class);
        $logRepo = Common::container()->get(BroadcastExecutionLogRepository::class);
        $deviceRepo = Common::container()->get(BroadcastDevicesRepository::class);
        $devices = $deviceRepo->list([
            'id' => $params['devices'],
        ])->toArray();
        $planRepo->getQuery()->where('id', $params['id'])
            ->update([
                'execution_count' => Db::raw('execution_count+1'),
                'last_execution_time' => date('Y:m:d H:i:s'),
            ]);
        echo "开始执行计划：{$params['id']}" . PHP_EOL;
        foreach ($devices as $device) {
            Coroutine::create(function () use ($logRepo, $device, $params) {
                $startTime = time();
                $log = $logRepo->create([
                    'plan_id' => $params['id'],
                    'start_time' => date('Y:m:d H:i:s', $startTime),
                    'execution_type' => $params['type'],
                    'execution_status' => Constant::EXECUTION_RUNNING,
                    'broadcast_content' => $params['content'],
                    'file' => $params['url'],
                    'volume_level' => $params['volume'],
                    'device_id' => $device['id'],
                ]);
                // todo 执行播放
                echo "++++++++++++++++++++++++++开始播放广播：计划" . $params['id'] . '，设备 ' . $device['id'] . PHP_EOL;
                try {
                    $res = true;
                    Coroutine::sleep(2);
                    $endTime = time();
                    echo "++++++++++++++++++++++++++播放完成：计划" . $params['id']  . '，设备 ' . $device['id'] . '，耗时 ' . ($endTime - $startTime) . '秒' . PHP_EOL;
                    $logUpdate = [
                        'status' => $res ? Constant::EXECUTION_SUCCESS : Constant::EXECUTION_FAILED,
                        'end_time' => date('Y-m-d H:i:s', $endTime),
                        'actual_duration' => $endTime - $startTime,
                        'fail_reason' => $res ? '' : '执行失败',
                    ];
                } catch (Throwable $e) {
                    echo "++++++++++++++++++++++++++播放异常: 计划". $params['id'] . '，设备 ' . $device['id'] . PHP_EOL;
                    $logUpdate = [
                        'status' => Constant::EXECUTION_FAILED,
                        'end_time' => date('Y-m-d H:i:s', $endTime),
                        'actual_duration' => $endTime - $startTime,
                        'fail_reason' => '执行异常',
                    ];
                    Common::logException(__CLASS__, $e);
                }

                $logRepo->updateById($log->id, $logUpdate);
            });
        }
        echo '计划' . $params['id'] . "计划执行完毕" . PHP_EOL;
    }
}
